import { Callout, Sandpack } from '@/components'

# useSuspenseQueries

<Callout type='warning'>

**@suspensive/react-query에서 Deprecated**

이 훅은 이제 TanStack Query v4.40.0+에서 공식적으로 지원됩니다. TanStack Query에서 백포팅했으므로, @suspensive/react-query의 백포팅된 버전을 deprecated 처리합니다. 공식 TanStack Query 인터페이스로 마이그레이션하세요:

```diff
- import { useSuspenseQueries } from '@suspensive/react-query'
+ import { useSuspenseQueries } from '@tanstack/react-query'
```

자세한 내용은 [TanStack Query PR #9140](https://github.com/TanStack/query/pull/9140)을 참고하세요.

</Callout>

이 hook의 return 타입에는 isLoading, isError이 없습니다. `<Suspense/>` and `<ErrorBoundary/>`가 이 hook의 data를 보장해주기 때문입니다. 또한, 이 hook의 options에는 기본적으로 suspense가 true입니다. 필요한 새 options는 @tanstack/react-query의 [useQueries](https://tanstack.com/query/v4/docs/react/reference/useQueries)처럼 사용하면 됩니다.

```tsx /useSuspenseQueries/
import { useSuspenseQueries } from '@suspensive/react-query'

const Example = () => {
  const [query1, query2] = useSuspenseQueries({
    queries: [
      { queryKey: [1], queryFn },
      { queryKey: [2], queryFn },
    ],
  }) // suspense: true가 기본입니다.

  // isSuccess으로 type narrowing이 필요하지 않습니다.
  query1.data // TData
  query2.data // TData
}
```

<Sandpack>

```tsx Post.tsx active
import { useSuspenseQueries } from '@suspensive/react-query'
import { getPost, getComments } from './api'

export const Post = ({ postId }: { postId: number }) => {
  const [postQuery, commentQuery] = useSuspenseQueries({
    queries: [
      { queryKey: ['posts', postId], queryFn: () => getPost(postId) },
      { queryKey: ['comments', postId], queryFn: () => getComments(postId) },
    ],
  })

  return (
    <div>
      <h1>{postQuery.data.title}</h1>
      <p>{postQuery.data.body}</p>
      <h2>Comments</h2>
      <ul>
        {commentQuery.data.map((comment) => (
          <li key={comment.id}>{comment.body}</li>
        ))}
      </ul>
    </div>
  )
}
```

```tsx Example.tsx
import { Suspense } from '@suspensive/react'
import { useState } from 'react'
import { Post } from './Post'

export const Example = () => {
  const [postId, setPostId] = useState(1)

  return (
    <div>
      <button
        onClick={() => setPostId((prev) => prev - 1)}
        disabled={postId === 1}
      >
        Previous Post
      </button>
      <button
        onClick={() => setPostId((prev) => prev + 1)}
        disabled={postId === 100}
      >
        Next Post
      </button>
      <Suspense fallback={<div>Loading...</div>}>
        <Post postId={postId} />
      </Suspense>
    </div>
  )
}
```

```tsx /api.ts
type Post = {
  userId: number
  id: number
  title: string
  body: string
}

export const getPost = async (id: number): Promise<Post> => {
  const response = await fetch(
    `https://jsonplaceholder.typicode.com/posts/${id}`
  )

  if (!response.ok) {
    throw new Error('An error occurred')
  }

  const data = await response.json()

  return data
}

type Comment = {
  postId: number
  id: number
  name: string
  email: string
  body: string
}

export const getComments = async (postId: number): Promise<Comment[]> => {
  const response = await fetch(
    `https://jsonplaceholder.typicode.com/comments?postId=${postId}`
  )

  if (!response.ok) {
    throw new Error('An error occurred')
  }

  const data = await response.json()

  return data
}
```

</Sandpack>

### 동기

@tanstack/react-query [useQueries](https://tanstack.com/query/v4/docs/react/reference/useQueries)의 suspense 옵션을 사용하면, useQueries를 `<Suspense/>`, `<ErrorBoundary/>`와 함께 사용할 수 있습니다.

```tsx /useQueries/
import { useQueries } from '@tanstack/react-query'

const Example = () => {
  const [query1, query2] = useQueries({
    queries: [
      { queryKey: [1], queryFn, suspense: true },
      { queryKey: [2], queryFn, suspense: true },
    ],
  })

  query1.data // TData | undefined
  query2.data // TData | undefined

  if (query1.isSuccess) {
    query1.data // TData
  }
  if (query2.isSuccess) {
    query2.data // TData
  }
}
```

useQueries의 return 타입(query1.data, query2.data)은 이 컴포넌트의 부모인 `<Suspense/>`와 `<ErrorBoundary/>` 덕분에 항상 성공한 경우일 것입니다.
하지만 @tanstack/react-query는 타입적으로 이것을 표현하지 않습니다.

이것이 @suspensive/react-query가 **useSuspenseQueries**를 제공하는 이유입니다.

<Callout>

성공한 케이스에 집중하세요.

이제 우리는 컴포넌트 내부에서 fetching이 항상 성공하므로 성공한 경우에만 집중할 수 있습니다.

</Callout>

### 버전 기록

| Version  | Changes                                                                                                                              |
| -------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| `v3.0.0` | `networkMode`는 `'always'`로 고정되었습니다. 자세한 내용은 [v3로 마이그레이션하기 문서](./migration/migrate-to-v3.mdx)를 참고하세요. |
